home *** CD-ROM | disk | FTP | other *** search
- // Copyright (c)1995 Ray Dream, Inc. All Rights Reserved.
- /* $Id: COMLite.cpp 1.5 1997/04/10 00:49:12 damien Exp $ */
-
- ////////////////////////////////////////////////////////////////////////
- // First Light Source Example : Beams Light //
- //--------------------------------------------------------------------//
- // Implementation of the Beams Light Interface //
- ////////////////////////////////////////////////////////////////////////
-
- #include "math.h"
-
- #ifndef __COMLITE__
- #include "COMLITE.h"
- #endif
-
- #ifndef __LITEDLL__
- #include "LITEDLL.h"
- #endif
-
- #ifndef __3DCOFAIL__
- #include "3DCoFail.h"
- #endif
-
- // Tool to get the Global Coordinates from the Local Coordinates
- void LocalToGlobal(TRANSFORM3D* transform,VECTOR3D* LocalPos,VECTOR3D* GlobalPos) {
- // Axes rotations
- (*GlobalPos)[0]=transform->fR.fix*(*LocalPos)[0]
- +transform->fR.fjx*(*LocalPos)[1]
- +transform->fR.fkx*(*LocalPos)[2];
- (*GlobalPos)[1]=transform->fR.fiy*(*LocalPos)[0]
- +transform->fR.fjy*(*LocalPos)[1]
- +transform->fR.fjy*(*LocalPos)[2];
- (*GlobalPos)[2]=transform->fR.fiz*(*LocalPos)[0]
- +transform->fR.fjz*(*LocalPos)[1]
- +transform->fR.fkz*(*LocalPos)[2];
- // Unit conversion : Points Units to 3D Units
- (*GlobalPos)[0] /= 288.0;
- (*GlobalPos)[1] /= 288.0;
- (*GlobalPos)[2] /= 288.0;
- // Origin translation
- (*GlobalPos)[0] += transform->fT[0];
- (*GlobalPos)[1] += transform->fT[1];
- (*GlobalPos)[2] += transform->fT[2];
- }
-
- // Tool to get the Global Coordinates from the Local Coordinates for a Vector
- void LocalToGlobalVector(TRANSFORM3D* transform,VECTOR3D* LocalPos,VECTOR3D* GlobalPos) {
- // Axes rotations
- (*GlobalPos)[0]=transform->fR.fix*(*LocalPos)[0]
- +transform->fR.fjx*(*LocalPos)[1]
- +transform->fR.fkx*(*LocalPos)[2];
- (*GlobalPos)[1]=transform->fR.fiy*(*LocalPos)[0]
- +transform->fR.fjy*(*LocalPos)[1]
- +transform->fR.fky*(*LocalPos)[2];
- (*GlobalPos)[2]=transform->fR.fiz*(*LocalPos)[0]
- +transform->fR.fjz*(*LocalPos)[1]
- +transform->fR.fkz*(*LocalPos)[2];
- }
-
- // Tool to get the Local Coordinates from the Global Coordinates
- void GlobalToLocal(TRANSFORM3D* transform,VECTOR3D* GlobalPos,VECTOR3D* LocalPos) {
- // Origin translation
- (*GlobalPos)[0] -= transform->fT[0];
- (*GlobalPos)[1] -= transform->fT[1];
- (*GlobalPos)[2] -= transform->fT[2];
- // Unit conversion : 3D Units to Points Units
- (*GlobalPos)[0] *= 288.0;
- (*GlobalPos)[1] *= 288.0;
- (*GlobalPos)[2] *= 288.0;
-
- // Axes rotations
- (*LocalPos)[0]=transform->fR.fix*(*GlobalPos)[0]
- +transform->fR.fiy*(*GlobalPos)[1]
- +transform->fR.fiz*(*GlobalPos)[2];
- (*LocalPos)[1]=transform->fR.fjx*(*GlobalPos)[0]
- +transform->fR.fjy*(*GlobalPos)[1]
- +transform->fR.fjz*(*GlobalPos)[2];
- (*LocalPos)[2]=transform->fR.fkx*(*GlobalPos)[0]
- +transform->fR.fky*(*GlobalPos)[1]
- +transform->fR.fkz*(*GlobalPos)[2];
- }
-
- // Tool to get the Local Coordinates from the Global Coordinates for a Vector
- void GlobalToLocalVector(TRANSFORM3D* transform,VECTOR3D* GlobalPos,VECTOR3D* LocalPos) {
-
- // Axes rotations
- (*LocalPos)[0]=transform->fR.fix*(*GlobalPos)[0]
- +transform->fR.fiy*(*GlobalPos)[1]
- +transform->fR.fiz*(*GlobalPos)[2];
- (*LocalPos)[1]=transform->fR.fjx*(*GlobalPos)[0]
- +transform->fR.fjy*(*GlobalPos)[1]
- +transform->fR.fjz*(*GlobalPos)[2];
- (*LocalPos)[2]=transform->fR.fkx*(*GlobalPos)[0]
- +transform->fR.fky*(*GlobalPos)[1]
- +transform->fR.fkz*(*GlobalPos)[2];
- }
-
-
-
-
-
- // Constructor / Destructor of the C++ Object :
- BeamsLight::BeamsLight() {
- fCRef=0; // Reference counter
- // Rotation Matrix initialized to identity :
- fTransform.fR.fix=fTransform.fR.fjy=fTransform.fR.fkz=1.0;
- fTransform.fR.fjx=fTransform.fR.fkx=0.0;
- fTransform.fR.fiy=fTransform.fR.fky=0.0;
- fTransform.fR.fiz=fTransform.fR.fjz=0.0;
- // Translation Vector initialized to zero :
- fTransform.fT[0]=fTransform.fT[1]=fTransform.fT[2]=0.0;
- // Data initialization :
- // -- Default color : White
- fData.fLightColor.Mode=0; // RGB Color
- fData.fLightColor.R=1.0;
- fData.fLightColor.G=1.0;
- fData.fLightColor.B=1.0;
- fData.fLightColor.A=0.0;
- // -- Aperture Angles
- fData.fHorApertureAngle=90; // 90∞ (-45∞ to 45∞)
- fData.fVerApertureAngle=90; //
- fData.fBeamAperture=5; // 5∞ for each beam
- // -- Intensity of the Beams
- fData.fIntensity=1.0; // 100% of intensity
- // -- Numbers of Beams
- fData.fNbBeamsHorizontally=10;
- fData.fNbBeamsVertically=10;
- ExtensionDataChanged(); // Preprocessed values
- }
-
- BeamsLight::~BeamsLight() {
- global_count_Obj--;
- }
-
- // IUnknown Interface :
- HRESULT BeamsLight::QueryInterface(THIS_ REFIID riid,LPVOID* ppvObj) {
- *ppvObj=NULL;
-
- // The BeamsLight knows the interfaces of the parent Objects
- if (IsEqualIID(riid, IID_IUnknown))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExLightsource))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExDataExchanger))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExtension))
- *ppvObj=(LPVOID)this;
-
- // we must add reference if we return an interface
- if (*ppvObj!=NULL) {
- ((LPUNKNOWN)*ppvObj)->AddRef();
- return NOERROR;
- }
- else {
- return ResultFromScode(E_NOINTERFACE);
- }
- }
-
- ULONG BeamsLight::AddRef(THIS) {
- return fCRef++;
- }
-
- ULONG BeamsLight::Release(THIS) {
- ULONG UnreleaseObject=fCRef--;
-
- if (fCRef==0)
- delete this; // No reference left so delete the object
-
- return UnreleaseObject;
- // Use local variable because if the object is destructed
- // fCRef do not exist
- }
-
- // I3DExtension methods :
- I3DExtension* BeamsLight::Clone(THIS) {
- BeamsLight* theClone = new BeamsLight;
- if (theClone) {
- theClone->AddRef();
- theClone->fTransform=fTransform; // Copy all the Data
- theClone->fData =fData;
- theClone->fVerAng =fVerAng;
- theClone->fHorAng =fHorAng;
- theClone->fBeamLimit=fBeamLimit;
- theClone->fBeamAngle=fBeamAngle;
- }
- return theClone;
- }
-
- HRESULT BeamsLight::ShellUtilitiesInit(THIS_ IShUtilities* shellUtilities) {
- InitCoFailure(shellUtilities);
- return NOERROR;
- }
-
- // I3DExDataExchanger methods :
- ExtensionDataMap* BeamsLight::GetExtensionDataMap(THIS) {
- return NULL;
- }
-
- void* BeamsLight::GetExtensionDataBuffer(THIS) {
- return &fData; // The Shell uses this pointer to set the values of the camera's parameters
- }
-
- HRESULT BeamsLight::ExtensionDataChanged(THIS) {
- fHorAng=((NUM3D)fData.fHorApertureAngle)/2.0; // Recalculate Aperture Angles
- fVerAng=((NUM3D)fData.fVerApertureAngle)/2.0;
- fBeamAngle=((NUM3D)fData.fBeamAperture)/2.0;
- fBeamLimit=cos(fBeamAngle/180.0*3.14159265358979323846); //QuickSinCos(fBeamAngle,sinus,cosinus);
- return NOERROR;
- }
-
- // This function is here, to allow you to create and use special resource.
- HRESULT BeamsLight::HandleEvent(THIS_ ULONG SourceID) {
- return ResultFromScode(E_NOTIMPL);
- }
-
- short BeamsLight::GetResID(THIS) {
- return 132; // This is the view ID in the resource file
- }
-
- // I3DExLightsource methods :
- // set the coordinates Transformation values
- HRESULT BeamsLight::SetTransform(THIS_ TRANSFORM3D* transform) {
- fTransform=*transform;
- return ResultFromScode(S_OK);
- }
-
- HRESULT BeamsLight::GetDirection(THIS_ VECTOR3D* position, VECTOR3D* resultDirection, NUM3D* resultDistance) {
- (*resultDirection)[0]=fTransform.fT[0]-(*position)[0];
- (*resultDirection)[1]=fTransform.fT[1]-(*position)[1];
- (*resultDirection)[2]=fTransform.fT[2]-(*position)[2]; // Vector from surface point to the BeamsLight
- *resultDistance=sqrt(SQR((*resultDirection)[0]) + SQR((*resultDirection)[1]) + SQR((*resultDirection)[2]));
- (*resultDirection)[0] /= *resultDistance;
- (*resultDirection)[1] /= *resultDistance;
- (*resultDirection)[2] /= *resultDistance;
- //*resultDistance=resultDirection->GetNorm(); // Distance from the point to the light
- //*resultDirection/=(*resultDistance); // Normalized vector
- return ResultFromScode(S_OK);
- }
-
-
- BOOLEAN BeamsLight::GetColor(THIS_ VECTOR3D* position, VECTOR3D* direction, NUM3D distance, COLOR3D* result, BOOLEAN* callForShadowEffect) {
- VECTOR3D localVector,refDir;
- NUM3D angle,nearest_dir,hor,ver,theta,phi,r;
- NUM3D costheta,sintheta,cosphi,sinphi;
- NUM3D cosdifferentialAngle;
- NUM3D angleLimit=360.0;
-
- *callForShadowEffect=TRUE; // We always want shadows for this lightsource
-
- GlobalToLocalVector(&fTransform,direction,&localVector);
-
- // initialize result to default color (intensity included)
- *result=fData.fLightColor;
- result->R*=fData.fIntensity;
- result->G*=fData.fIntensity;
- result->B*=fData.fIntensity;
-
- // Nearest direction vector determination
-
- if (fData.fNbBeamsHorizontally!=1) {
- // direction is calculated in the Spherical Coordinates (see Spheric Camera)
- // -- Horizontal Determination
- angle=atan2(localVector[0],localVector[2])*180.0/3.14159265358979323846; //QuickArcSinCos(localVector[0],localVector[2],angle);
- if (angle>angleLimit/2.0) {
- angle-=angleLimit;
- }
- if ((angle>fHorAng+fBeamAngle)||(angle<-fHorAng-fBeamAngle)) return FALSE; // the point is outside the maximum horizontal aperture
-
- nearest_dir=(angle/(fHorAng*2.0)+0.5)*((NUM3D)fData.fNbBeamsHorizontally-1.0);
- hor=floor(nearest_dir);
- if (nearest_dir-hor>0.5) hor+=1.0;
- if (hor>((NUM3D)fData.fNbBeamsHorizontally-1.0)) hor=((NUM3D)fData.fNbBeamsHorizontally-1.0);
- if (hor<0.0) hor=0.0;
- // hor must be between 0 and fNbBeamsHorizontally-1
- theta=fHorAng*2.0*(hor/((NUM3D)fData.fNbBeamsHorizontally-1)-0.5);
- }
- else {
- theta=0.0;
- }
- if (fData.fNbBeamsVertically!=1) {
- // -- Vertical Determination
- r=localVector[0]*localVector[0]+localVector[2]*localVector[2];
- r=sqrt(r);
- angle=atan2(localVector[1],r)*180.0/3.14159265358979323846; //QuickArcSinCos(localVector[1],r,angle);
- if (angle>(angleLimit/2.0)) {
- angle-=angleLimit;
- }
- if ((angle>fVerAng+fBeamAngle)||(angle<-fVerAng-fBeamAngle)) return FALSE; // the point is outside the maximum vertical aperture
- nearest_dir=(angle/(fVerAng*2.0)+0.5)*((NUM3D)fData.fNbBeamsVertically-1.0);
- ver=floor(nearest_dir);
- if (nearest_dir-ver>0.5) ver+=1.0;
- if (ver>((NUM3D)fData.fNbBeamsVertically-1.0)) ver=((NUM3D)fData.fNbBeamsVertically-1.0);
- if (ver<0.0) ver=0.0;
- // ver must be between 0 and fNbBeamsVertically-1
- phi=(fVerAng*2.0)*(ver/((NUM3D)fData.fNbBeamsVertically-1.0)-0.5);
- }
- else {
- phi=0.0;
- }
- // nearest direction vector
-
- // Spherical Coordinates of the direction vector
- sintheta=sin(theta/180.0*3.14159265358979323846);
- costheta=cos(theta/180.0*3.14159265358979323846); //QuickSinCos(theta,sintheta,costheta);
- sinphi=sin(phi/180.0*3.14159265358979323846);
- cosphi=cos(phi/180.0*3.14159265358979323846); //QuickSinCos(phi,sinphi,cosphi);
- refDir[0]=sintheta*cosphi;
- refDir[1]=sinphi;
- refDir[2]=costheta*cosphi;
- // Direction comparaison
- cosdifferentialAngle=refDir[0]*localVector[0] + // dot product to get the cosinus of the angle
- refDir[1]*localVector[1] +
- refDir[2]*localVector[2];
- if (cosdifferentialAngle<fBeamLimit) return FALSE; // the point is outside the Beam
- return TRUE;
- }
-
- // can the light source be visible in the 3D perspective display
- BOOLEAN BeamsLight::IsVisibleInPerspective(THIS) {
- return TRUE; // the source is not a distant light (like the sun)
- // so it can be in the 3D perspective display.
- }
-
- // the BeamsLight gives a perfect shadow effect (no light behind an object)
- HRESULT BeamsLight::ShadowEffect(THIS_ NUM3D distance, COLOR3D* result) {
- result->R=0.0;
- result->G=0.0;
- result->B=0.0;
- return ResultFromScode(S_OK);
- }
-
-
- LightTraceElement* BeamsLight::GetNewTrace(THIS_ short* nb) {
- return NULL;
- }
-
- ULONG BeamsLight::GetPrimitiveID(THIS) {
- return 0;
- }
-
- HRESULT BeamsLight::ForEachShadowBuffer(THIS_ ForEachShadowBufferCallback proc, void* priv) {
- /*** to do ***/
- return ResultFromScode(E_NOTIMPL);
- }
-
- HRESULT BeamsLight::GetLightParameter(THIS_ long keyword, void* parameter) {
- return ResultFromScode(E_NOTIMPL);
- }
-